package com.syh.jn.scm.service.impl.downstream.logistics;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.event.annotation.DomainEventHandle;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.ddd.service.AbstractServiceImpl;
import com.syh.jn.scm.domain.downstream.entity.logistics.DownLogisticsBill;
import com.syh.jn.scm.domain.downstream.entity.logistics.DownLogisticsBillItem;
import com.syh.jn.scm.domain.downstream.event.DownLogisticsBillEvent;
import com.syh.jn.scm.domain.downstream.repository.logistics.DownLogisticsBillRepository;
import com.syh.jn.scm.domain.supplier.entity.logistics.LogisticsBill;
import com.syh.jn.scm.domain.supplier.event.LogisticsBillEvent;
import com.syh.jn.scm.dto.downstream.logistics.DownLogisticsBillItemVo;
import com.syh.jn.scm.dto.downstream.logistics.DownLogisticsBillMto;
import com.syh.jn.scm.dto.downstream.logistics.DownLogisticsBillSto;
import com.syh.jn.scm.dto.downstream.logistics.DownLogisticsBillVo;
import com.syh.jn.scm.service.api.downstream.logistics.DownLogisticsBillService;
import com.syh.jn.scm.service.api.downstream.logistics.enums.DownLogisticsBillEnums;
import com.syh.jn.scm.service.api.supplier.logistics.enums.LogisticsBillEnums;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by soci.song on 2018/11/2.
 */
@Service
@Transactional
public class DownLogisticsBillServiceImpl extends AbstractServiceImpl<DownLogisticsBillSto, DownLogisticsBillMto, DownLogisticsBillVo, DownLogisticsBill, Long> implements DownLogisticsBillService {
  @Autowired
  private DownLogisticsBillRepository downLogisticsBillRepository;

  @Override
  protected AggregateRepository<DownLogisticsBill, Long> getAggregateRepository() {
    return downLogisticsBillRepository;
  }

  /**
   * 创建物流单
   *
   * @param logisticsBillSto
   * @return
   */
  @Override
  public Long save(DownLogisticsBillSto logisticsBillSto) {
    DownLogisticsBill logisticsBill = new DownLogisticsBill(logisticsBillSto);
    Long id = downLogisticsBillRepository.add(logisticsBill);
    this.publicEvent(DownLogisticsBillEvent.bulidDownLogisticsBillCreated(new Object[]{logisticsBill}));
    //当不是物流发货时,自动进行出车操作
    if (!logisticsBill.getDeliveryType().equals(DownLogisticsBillEnums.DeliveryType.LOGISTICS_TYPE.getDeliveryType())) {
      this.delivery(id);
    }
    return id;
  }

  /**
   * 修改物流单
   *
   * @param mto
   */
  @Override
  public void update(DownLogisticsBillMto mto) {
    DownLogisticsBill logisticsBill = judgeNull(mto.getId());
    logisticsBill.modify(mto);
    downLogisticsBillRepository.update(logisticsBill);
    if (logisticsBill.getSecondaryBill() != null) {
      downLogisticsBillRepository.update(logisticsBill.getSecondaryBill());
    }
  }

  @Override
  public void delivery(Long id) {
    DownLogisticsBill logisticsBill = downLogisticsBillRepository.getById(id);
    logisticsBill.delivery();
    downLogisticsBillRepository.updateStatus(logisticsBill);
    this.publicEvent(DownLogisticsBillEvent.bulidDownLogisticsBillDelivery(new Object[]{logisticsBill}));
  }


  @Override
  public void collect(Long id) {
    DownLogisticsBill logisticsBill = downLogisticsBillRepository.getById(id);
    logisticsBill.collect();
    downLogisticsBillRepository.updateStatus(logisticsBill);
    this.publicEvent(DownLogisticsBillEvent.bulidDownLogisticsBillCollected(new Object[]{logisticsBill}));
    if (logisticsBill.getSubjectBillId() != null) {
      this.publicEvent(DownLogisticsBillEvent.bulidPurchaseSaleLogisticsBillCollected(new Object[]{logisticsBill}));
    }
  }

  /**
   * 消费者(监听服务商销售退货取消签收)
   *
   * @param logisticsBill
   */
  @DomainEventHandle(LogisticsBillEvent.LOGISTICS_BILL_UN_RECEIVED)
  public void handelLogisticsBillUnReceived(LogisticsBill logisticsBill, LogisticsBill oldLogisticsBill) {
    if (!logisticsBill.getDeliveryType().equals(LogisticsBillEnums.DeliveryType.LOGISTICS_TYPE.getDeliveryType())) {
      //如果是下游采购退货的取消签收 则一起取消发货
      if (logisticsBill.getOrderType().equals(DownLogisticsBillEnums.OrderType.RETURN_PURCHASE.getStatus())) {
        this.cancel(logisticsBill.getId());
      }
    }
  }

  /**
   * 取消物流单
   *
   * @param id
   */
  @Override
  public void cancel(Long id) {
    DownLogisticsBill logisticsBill = downLogisticsBillRepository.getById(id);
    logisticsBill.cancel();
    downLogisticsBillRepository.updateStatus(logisticsBill);
    this.publicEvent(DownLogisticsBillEvent.bulidDownLogisticsBillCancelled(new Object[]{logisticsBill}));
  }

  @Override
  public void cancelReceipt(Long id) {
    DownLogisticsBill logisticsBill = downLogisticsBillRepository.getById(id);
    DownLogisticsBill oldBill = downLogisticsBillRepository.getById(id);
    logisticsBill.cancelReceipt();
    downLogisticsBillRepository.updateStatus(logisticsBill);
    this.publicEvent(DownLogisticsBillEvent.bulidDownLogisticsBillUnReceived(new Object[]{logisticsBill,oldBill}));
    if (logisticsBill.getSubjectBillId() != null) {
      this.publicEvent(DownLogisticsBillEvent.bulidPurchaseSaleLogisticsBillUnReceived(new Object[]{logisticsBill}));
    }
  }

  @Override
  public void remove(Long id) {
    DownLogisticsBill logisticsBill = downLogisticsBillRepository.getById(id);
    logisticsBill.setItems(downLogisticsBillRepository.getItemsByLogisticsBillId(logisticsBill.getId()));
    //如果不是物流发货 且是已发车状态 先取消发货
    if (!logisticsBill.getDeliveryType().equals(DownLogisticsBillEnums.DeliveryType.LOGISTICS_TYPE.getDeliveryType())
            && logisticsBill.getLogisticsState().equals(DownLogisticsBillEnums.State.DELIVEED.getStatus())) {
      this.cancel(id);
      logisticsBill = downLogisticsBillRepository.getById(id);
      logisticsBill.setItems(downLogisticsBillRepository.getItemsByLogisticsBillId(logisticsBill.getId()));
    }
    logisticsBill.remove();
    downLogisticsBillRepository.removeById(id);
    this.publicEvent(DownLogisticsBillEvent.bulidDownLogisticsBillDeleted(new Object[]{logisticsBill}));
  }

  /**
   * 判空方法
   *
   * @param id
   * @return
   */
  private DownLogisticsBill judgeNull(Long id) {
    ExtAssert.notNull(id, "id不能为空");
    DownLogisticsBill entity = downLogisticsBillRepository.getById(id);
    ExtAssert.notNull(entity, "订单不存在");
    return entity;
  }

  @Override
  public List<DownLogisticsBillItemVo> getItemsByLogisticsBillId(Long id) {
    return transformLogistics(downLogisticsBillRepository.getItemsByLogisticsBillId(id));
  }

  @Override
  public List<DownLogisticsBillVo> getLogisticsBillVosByOrderId(Long id, Short orderType) {
    Wrapper we = Wrapper.build();
    we.append(Restrictions.eq("orderType", orderType));
    we.append(Restrictions.eq("orderId", id));
    List<DownLogisticsBillVo> billVos = downLogisticsBillRepository.getListView(we);
    billVos.forEach(vo -> {
      List<DownLogisticsBillItemVo> itemVos = transformLogistics(downLogisticsBillRepository.getItemsByLogisticsBillId(vo.getId()));
      vo.setItems(itemVos);
    });
    return billVos;
  }

  /**
   * 内部方法  领域对象转vo
   *
   * @param entityList
   * @return
   */
  private List<DownLogisticsBillItemVo> transformLogistics(List<DownLogisticsBillItem> entityList) {
    List<DownLogisticsBillItemVo> voList = new ArrayList<>();
    entityList.stream().forEach((entity) -> {
      DownLogisticsBillItemVo vo = new DownLogisticsBillItemVo();
      ExtBeanUtils.copyProperties(entity, vo);
      voList.add(vo);
    });
    return voList;
  }

  private DownLogisticsBillItemVo trans(DownLogisticsBillItem entity) {
    DownLogisticsBillItemVo vo = new DownLogisticsBillItemVo();
    ExtBeanUtils.copyProperties(entity, vo);
    return vo;
  }
}
